// Copyright (c) Microsoft
// All rights reserved
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
// INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
// See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
/// <tags>P1</tags>
/// <summary>Test tile() member function on different extents of extent(2D) and tile by 1D and 2D.</summary>
// RUN: %amp_device -D__GPU__ %s -m32 -emit-llvm -c -S -O3 -o %t.ll && mkdir -p %t
// RUN: %llc -march=c -o %t/kernel_.cl < %t.ll
// RUN: cat %opencl_math_dir/opencl_math.cl %t/kernel_.cl > %t/kernel.cl
// RUN: pushd %t && objcopy -B i386:x86-64 -I binary -O elf64-x86-64 kernel.cl %t/kernel.o && popd
// RUN: %cxxamp %link %t/kernel.o %s -o %t.out && %t.out
#include "./../tile.h"

#define INVOKE_TEST_FUNC_ON_CPU_AND_GPU(_func, ...) [&]() { \
    /* Invoke on cpu */ \
    int cpu_result = _func(__VA_ARGS__); \
    /* Invoke on gpu */ \
    int gpu_result; \
    concurrency::array_view<int, 1> gpu_resultv(1, &gpu_result); \
    gpu_resultv.discard_data(); \
    concurrency::parallel_for_each(gpu_resultv.get_extent() \
        , [=](concurrency::index<1> idx) restrict(amp) { \
        gpu_resultv[idx] = _func(__VA_ARGS__); \
    }); \
    gpu_resultv.synchronize(); \
        return cpu_result & gpu_result; \
}()

template<typename _type>
bool test_tile() restrict(amp,cpu)
{
            // cubed extent in x, y, z
    return  test_tile_3d<_type, 1, 1, 1>() && test_tile_3d<_type, 11, 11, 11>() && 
            test_tile_3d<_type, 1000, 1000, 1000>() && test_tile_3d<_type, 16, 16, 16>() &&
            // almost 2D block extent in x, y, z
            test_tile_3d<_type,   1,   11, 1000>() && 
            test_tile_3d<_type,  16, 1000, 1>() &&
            test_tile_3d<_type, 1000,  16, 11>() && 
            test_tile_3d<_type,   11,   1, 16>();
            
}

int main() 
{
	//accelerator_view av = require_device().get_default_view();

	int result = 1;
	result &= INVOKE_TEST_FUNC_ON_CPU_AND_GPU([]() restrict(amp,cpu)->bool{return test_tile<extent<3>>();});
	return !result;
}
